﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using nHydrate.EFCore.DataAccess;
using Acme.Sakila.TestSite;
using Acme.Sakila.EFDAL.Interfaces;

namespace Acme.Sakila.TestSite.Objects
{
	public class ORMMap
	{
		private readonly Dictionary<Control, bool> _bindableControlList = new Dictionary<Control, bool>();
		private readonly IContext _context;
		private readonly Dictionary<Control, MapConfiguration> _controlList = new Dictionary<Control, MapConfiguration>();
		private readonly Dictionary<Control, MapConfiguration> _promptControlList = new Dictionary<Control, MapConfiguration>();

		#region Constructors

		public ORMMap(IContext context)
		{
			if (context == null)
				throw new Exception("The context must be set!");
			_context = context;
		}

		#endregion

		#region Public Map and Initailize Methods

		public virtual MapConfiguration Map(MapConfiguration configuration)
		{
			return MapInternal(configuration);
		}

		public virtual MapConfiguration Map(MapConfiguration configuration, Literal promptControl)
		{
			MapPromptInternal(new MapConfiguration
													{
														Control = promptControl,
														Entity = configuration.Entity,
														Field = configuration.Field,
														Type = typeof(string),
														CanHaveRequiredValidation = configuration.CanHaveRequiredValidation,
														ForceRequiredValidation = configuration.ForceRequiredValidation,
														ValidationGroup = string.Empty,
														ErrorMessage = string.Empty,
														DataFormatString = configuration.DataFormatString,
													});

			return MapInternal(configuration);
		}

		public virtual MapConfiguration Map(TextBox control, INHEntityObject entity, Enum field)
		{
			return Map(control, entity, field, false);
		}

		public virtual MapConfiguration Map(TextBox control, INHEntityObject entity, Enum field, bool forceRequiredValidation)
		{
			return MapInternal(new MapConfiguration
										{
											Control = control,
											Entity = entity,
											Field = field,
											CanHaveRequiredValidation = true,
											ForceRequiredValidation = forceRequiredValidation,
										});
		}

		public virtual MapConfiguration Map(TextBox control, INHEntityObject entity, Enum field, Literal promptControl)
		{
			return Map(control, entity, field, promptControl, false);
		}

		public virtual MapConfiguration Map(TextBox control, INHEntityObject entity, Enum field, Literal promptControl, bool forceRequiredValidation)
		{
			MapPromptInternal(new MapConfiguration
													{
														Control = promptControl,
														Entity = entity,
														Field = field,
														Type = typeof(string),
														CanHaveRequiredValidation = true,
														ForceRequiredValidation = forceRequiredValidation
													});

			return Map(control, entity, field, forceRequiredValidation);
		}

		public virtual MapConfiguration Map(CheckBox control, INHEntityObject entity, Enum field)
		{
			return Map(control, entity, field, false);
		}

		public virtual MapConfiguration Map(CheckBox control, INHEntityObject entity, Enum field, bool forceRequiredValidation)
		{
			return MapInternal(new MapConfiguration
										{
											Control = control,
											Entity = entity,
											Field = field,
											CanHaveRequiredValidation = false,
											ForceRequiredValidation = forceRequiredValidation
										});
		}

		public virtual MapConfiguration Map(CheckBox control, INHEntityObject entity, Enum field, Literal promptControl)
		{
			return Map(control, entity, field, promptControl, false);
		}

		public virtual MapConfiguration Map(CheckBox control, INHEntityObject entity, Enum field, Literal promptControl,
														bool forceRequiredValidation)
		{
			MapPromptInternal(new MapConfiguration
													{
														Control = promptControl,
														Entity = entity,
														Field = field,
														Type = typeof(string),
														CanHaveRequiredValidation = false,
														ForceRequiredValidation = forceRequiredValidation
													});

			return Map(control, entity, field, forceRequiredValidation);
		}

		public virtual MapConfiguration Map(RadioButton control, INHEntityObject entity, Enum field)
		{
			return Map(control, entity, field, false);
		}

		public virtual MapConfiguration Map(RadioButton control, INHEntityObject entity, Enum field, bool forceRequiredValidation)
		{
			return MapInternal(new MapConfiguration
										{
											Control = control,
											Entity = entity,
											Field = field,
											CanHaveRequiredValidation = false,
											ForceRequiredValidation = forceRequiredValidation
										});
		}

		public virtual MapConfiguration Map(RadioButton control, INHEntityObject entity, Enum field, Literal promptControl)
		{
			return Map(control, entity, field, promptControl, false);
		}

		public virtual MapConfiguration Map(RadioButton control, INHEntityObject entity, Enum field, Literal promptControl,
														bool forceRequiredValidation)
		{
			MapPromptInternal(new MapConfiguration
													{
														Control = promptControl,
														Entity = entity,
														Field = field,
														Type = typeof(string),
														CanHaveRequiredValidation = false,
														ForceRequiredValidation = forceRequiredValidation
													});

			return Map(control, entity, field, forceRequiredValidation);
		}

		public virtual MapConfiguration Map(DropDownList control, INHEntityObject entity, Enum field)
		{
			return Map(control, entity, field, false);
		}

		public virtual MapConfiguration Map(DropDownList control, INHEntityObject entity, Enum field, bool forceRequiredValidation)
		{
			return MapInternal(new MapConfiguration
										{
											Control = control,
											Entity = entity,
											Field = field,
											CanHaveRequiredValidation = true,
											ForceRequiredValidation = forceRequiredValidation
										});
		}

		public virtual MapConfiguration Map(DropDownList control, INHEntityObject entity, Enum field, Literal promptControl)
		{
			return Map(control, entity, field, promptControl, false);
		}

		public virtual MapConfiguration Map(DropDownList control, INHEntityObject entity, Enum field, Literal promptControl,														bool forceRequiredValidation)
		{
			MapPromptInternal(new MapConfiguration
													{
														Control = promptControl,
														Entity = entity,
														Field = field,
														Type = typeof(string),
														CanHaveRequiredValidation = true,
														ForceRequiredValidation = forceRequiredValidation
													});

			return Map(control, entity, field, forceRequiredValidation);
		}

		public virtual MapConfiguration Map(Label control, INHEntityObject entity, Enum field)
		{
			return MapInternal(new MapConfiguration
										{
											Control = control,
											Entity = entity,
											Field = field,
											CanHaveRequiredValidation = true,
											ForceRequiredValidation = false
										});
		}

		public virtual MapConfiguration Map(Literal control, INHEntityObject entity, Enum field)
		{
			return MapInternal(new MapConfiguration
										{
											Control = control,
											Entity = entity,
											Field = field,
											CanHaveRequiredValidation = false,
											ForceRequiredValidation = false
										});
		}

		public virtual MapConfiguration Map(Literal control, INHEntityObject entity, Enum field, Literal promptControl)
		{
			MapPromptInternal(new MapConfiguration
													{
														Control = promptControl,
														Entity = entity,
														Field = field,
														Type = typeof(string),
														CanHaveRequiredValidation = true,
														ForceRequiredValidation = false
													});

			return Map(control, entity, field);
		}

		public virtual MapConfiguration Map(PlaceHolder control, INHEntityObject entity, Enum field)
		{
			return MapInternal(new MapConfiguration
										{
											Control = control,
											Entity = entity,
											Field = field,
											CanHaveRequiredValidation = false,
											ForceRequiredValidation = false
										});
		}

		public virtual void InitializeList(DropDownList control,
																			 IEnumerable<INHEntityObject> dataList,
																			 Enum textField,
																			 Enum valueField)
		{
			InitializeList(control, dataList, textField, valueField, true);
		}

		public virtual void InitializeList(DropDownList control,
																			 IEnumerable<INHEntityObject> dataList,
																			 Enum textField,
																			 Enum valueField,
																			 bool addFirstItem)
		{
			control.AppendDataBoundItems = true;
			control.DataTextField = textField.ToString();
			control.DataValueField = valueField.ToString();
			control.DataSource = dataList;
			_bindableControlList[control] = addFirstItem;
		}

		public static void BindList(DropDownList control,
																IEnumerable<INHEntityObject> dataList,
																Enum textField,
																Enum valueField,
																bool addFirstItem)
		{
			control.AppendDataBoundItems = true;
			control.DataTextField = textField.ToString();
			control.DataValueField = valueField.ToString();
			control.DataSource = dataList;
			control.DataBind();
			if (addFirstItem) control.Items.Insert(0, new ListItem("(Choose Item)", string.Empty));
		}

		public virtual void InitializeList(CheckBoxList control,
																			 IEnumerable<INHEntityObject> dataList,
																			 Enum textField,
																			 Enum valueField)
		{
			control.AppendDataBoundItems = true;
			control.DataTextField = textField.ToString();
			control.DataValueField = valueField.ToString();
			control.DataSource = dataList;
			_bindableControlList[control] = false;
		}

		public virtual void InitializeList(RadioButtonList control,
																			 IEnumerable<INHEntityObject> dataList,
																			 Enum textField,
																			 Enum valueField)
		{
			control.AppendDataBoundItems = true;
			control.DataTextField = textField.ToString();
			control.DataValueField = valueField.ToString();
			control.DataSource = dataList;
			_bindableControlList[control] = false;
		}

		#endregion

		#region Public Data Methods

		public virtual void DataPersist()
		{
			foreach (Control control in _controlList.Keys)
			{
				MapConfiguration e = _controlList[control];
				var entity = e.Entity as IBusinessObject;
				if (entity == null)
					throw new Exception("The entity is not persistable!");

				if (control is TextBox)
				{
					var c = control as TextBox;
					if (IsNullable(e.Field) && string.IsNullOrEmpty(c.Text) && e.EmptyAsNull)
						entity.SetValue(e.Field, null);
					else
						entity.SetValue(e.Field, ValidateValue(e, c.Text));
				}
				else if (control is CheckBox)
				{
					var c = control as CheckBox;
					entity.SetValue(e.Field, c.Checked);
				}
				else if (control is RadioButtonList)
				{
					var c = control as RadioButtonList;
					entity.SetValue(e.Field, ValidateValue(e, c.SelectedValue));
				}
				else if (control is DropDownList)
				{
					var c = control as DropDownList;
					entity.SetValue(e.Field, ValidateValue(e, c.SelectedValue));
				}
				else if (control is Label)
				{
					// do nothing 
				}
				else if (control is Literal)
				{
					// do nothing 
				}
				else if (control is PlaceHolder)
				{
					// do nothing 
				}

				else
				{
					throw new Exception("Unknown control type");
				}
			}
		}

		public virtual void DataBind()
		{
			//Bind each control to populate it
			foreach (Control control in _bindableControlList.Keys)
			{
				bool b = _bindableControlList[control];
				control.DataBind();
				if (b && control is DropDownList)
					((DropDownList)control).Items.Insert(0, new ListItem("(Choose Item)", string.Empty));
			}

			foreach (Control control in _controlList.Keys)
			{
				var e = _controlList[control];
				if (control is TextBox)
				{
					var c = control as TextBox;
					if (((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field) != null)
					{
						if (string.IsNullOrEmpty(e.DataFormatString))
							c.Text = ((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field).ToString();
						else
							c.Text = FormatText(((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field), e.DataFormatString);
					}
				}
				else if (control is CheckBox)
				{
					var c = control as CheckBox;
					object v = ((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field);
					if (v == null) c.Checked = false;
					else c.Checked = (bool)v;
				}
				else if (control is RadioButtonList)
				{
					var c = control as RadioButtonList;
					object v = ((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field);
					if (v == null) c.SelectedIndex = 0;
					else c.SelectedValue = v.ToString();
				}
				else if (control is DropDownList)
				{
					var c = control as DropDownList;
					object v = ((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field);
					if (v == null) c.SelectedIndex = 0;
					else c.SelectedValue = v.ToString();
				}
				else if (control is Label)
				{
					var c = control as Label;
					object o = ((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field);
					if (o != null)
					{
						if (string.IsNullOrEmpty(e.DataFormatString))
							c.Text = o.ToString();
						else
							c.Text = FormatText(o, e.DataFormatString);
					}
				}
				else if (control is Literal)
				{
					var c = control as Literal;
					object o = ((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field);
					if (o != null)
					{
						if (string.IsNullOrEmpty(e.DataFormatString))
							c.Text = o.ToString();
						else
							c.Text = FormatText(o, e.DataFormatString);
					}
				}
				else if (control is PlaceHolder)
				{
					var c = control as PlaceHolder;
					object o = ((IReadOnlyBusinessObject)e.Entity).GetValue(e.Field);
					if (o != null)
					{
						bool b;
						if (bool.TryParse(o.ToString().ToLower(), out b))
							c.Visible = b;
					}
				}
				else
				{
					throw new Exception("Unknown control type");
				}
			}

			foreach (Control control in _promptControlList.Keys)
			{
				MapConfiguration e = _promptControlList[control];

				string startChar = NeedsValidatorRequired(e.Field, e.CanHaveRequiredValidation, e.ForceRequiredValidation)
														? "*"
														: "&nbsp;";

				if (control is Literal)
				{
					var c = control as Literal;
					c.Text = string.Format("{0} {1}", startChar, GetDisplayName(e.Field));
				}

				else if (control is Label)
				{
					var c = control as Label;
					c.Text = string.Format("{0} {1}", startChar, GetDisplayName(e.Field));
				}
				else
				{
					throw new Exception("Unknown prompt control type");
				}
			}
		}

		#endregion

		#region Public Methods

		public virtual IEnumerable<BaseValidator> GetValidators()
		{
			var retval = new List<BaseValidator>();
			foreach (Control control in _controlList.Keys)
			{
				if (control.IsValidatable())
				{
					MapConfiguration e = _controlList[control];

					if (e.Entity != null)
					{
						//Determine if we need a required field validator
						if (NeedsValidatorRequired(e.Field, e.CanHaveRequiredValidation, e.ForceRequiredValidation))
						{
							var r1 = new RequiredFieldValidator
												{
													ControlToValidate = control.UniqueID,
													Display = ValidatorDisplay.None,
													ValidationGroup = e.ValidationGroup,
													ErrorMessage = "The '" + GetDisplayName(e.Field) + "' field is required!"
												};
							r1.Attributes.Add("CustomAttribute", e.CustomAttribute);
							retval.Add(r1);
						}

						//Determine if we need a regular expresion validator
						if (NeedsValidatorExpression(e.Field))
						{
							var r1 = new RegularExpressionValidator
												{
													ControlToValidate = control.UniqueID,
													Display = ValidatorDisplay.None,
													ValidationExpression = GetRegularExpression(e.Field),
													ValidationGroup = e.ValidationGroup,
													ErrorMessage = string.IsNullOrEmpty(e.ErrorMessage)
																					? "The '" + GetDisplayName(e.Field) + "' field is not the correct format!"
																					: e.ErrorMessage
												};
							r1.Attributes.Add("CustomAttribute", e.CustomAttribute);
							retval.Add(r1);
						}

						//Determine if we need a regular expresion validator
						if (NeedsValidatorMinMax(e.Field))
						{
							double min = GetMinValue(e.Field).Value;
							double max = GetMaxValue(e.Field).Value;
							var r1 = new RangeValidator
												{
													ControlToValidate = control.UniqueID,
													Display = ValidatorDisplay.None,
													MinimumValue = min.ToString(),
													MaximumValue = max.ToString(),
													ValidationGroup = e.ValidationGroup,
													ErrorMessage =
														"The '" + GetDisplayName(e.Field) + "' field is outside the range [" + min + ".." + max + "]"
												};
							r1.Attributes.Add("CustomAttribute", e.CustomAttribute);
							retval.Add(r1);
						}
					}
				}
			}
			return retval;
		}

		public static IEnumerable<BaseValidator> GetValidators(IEnumerable<ValidationRule> validationRules)
		{
			var retval = new List<BaseValidator>();
			foreach (ValidationRule r in validationRules)
			{
				if (r.Control.IsValidatable())
				{
					//Determine if we need a required field validator
					if (r.IsRequired)
					{
						var r1 = new RequiredFieldValidator
											{
												ControlToValidate = r.Control.UniqueID,
												Display = ValidatorDisplay.None,
												ErrorMessage = "The '" + r.FieldName + "' is required!",
												ValidationGroup = r.ValidationGroup,
											};
						r1.Attributes.Add("CustomAttribute", r.CustomAttribute);
						retval.Add(r1);
					}

					//Determine if we need a regular expresion validator
					if (!string.IsNullOrEmpty(r.ValidationExpression))
					{
						var r1 = new RegularExpressionValidator
											{
												ControlToValidate = r.Control.UniqueID,
												Display = ValidatorDisplay.None,
												ErrorMessage = "The '" + r.FieldName + "' is not the correct format!",
												ValidationExpression = r.ValidationExpression,
												ValidationGroup = r.ValidationGroup,
											};
						r1.Attributes.Add("CustomAttribute", r.CustomAttribute);
						retval.Add(r1);
					}
				}
			}
			return retval;
		}

		#endregion

		#region Private Helper Methods

		private object ValidateValue(MapConfiguration info, object value)
		{
			if (info.Type == null) return value;
			if (value == null) return value;

			if (info.Type == typeof(string))
			{
				return value;
			}
			else if ((info.Type == typeof(long)) || (info.Type == typeof(long?)))
			{
				long v;
				if (!long.TryParse(value.ToString().Replace("$", string.Empty), out v))
				{
					//If this is an empty string and the field is nullable then return null
					//otherwise thow an error
					if (value.ToString() == string.Empty && IsNullable(info.Field))
						return null;
					else
						throw new Exception("The value for '" + GetDisplayName(info.Field) + "' is not a valid long.");
				}
				else return v;
			}
			else if ((info.Type == typeof(int)) || (info.Type == typeof(int?)))
			{
				int v;
				if (!int.TryParse(value.ToString().Replace("$", string.Empty), out v))
				{
					//If this is an empty string and the field is nullable then return null
					//otherwise thow an error
					if (value.ToString() == string.Empty && IsNullable(info.Field))
						return null;
					else
						throw new Exception("The value for '" + GetDisplayName(info.Field) + "' is not a valid integer.");
				}
				else return v;
			}
			else if ((info.Type == typeof(byte)) || (info.Type == typeof(byte?)))
			{
				byte v;
				if (!byte.TryParse(value.ToString().Replace("$", string.Empty), out v))
				{
					//If this is an empty string and the field is nullable then return null
					//otherwise thow an error
					if (value.ToString() == string.Empty && IsNullable(info.Field))
						return null;
					else
						throw new Exception("The value for '" + GetDisplayName(info.Field) + "' is not a valid byte.");
				}
				else return v;
			}
			else if ((info.Type == typeof(short)) || (info.Type == typeof(short?)))
			{
				short v;
				if (!short.TryParse(value.ToString().Replace("$", string.Empty), out v))
				{
					//If this is an empty string and the field is nullable then return null
					//otherwise thow an error
					if (value.ToString() == string.Empty && IsNullable(info.Field))
						return null;
					else
						throw new Exception("The value for '" + GetDisplayName(info.Field) + "' is not a valid short.");
				}
				else return v;
			}
			else if ((info.Type == typeof(DateTime)) || (info.Type == typeof(DateTime?)))
			{
				DateTime v;
				if (!DateTime.TryParse(value.ToString(), out v))
				{
					//If this is an empty string and the field is nullable then return null
					//otherwise thow an error
					if (value.ToString() == string.Empty && IsNullable(info.Field))
						return null;
					else
						throw new Exception("The value for '" + GetDisplayName(info.Field) + "' is not a valid datetime.");
				}
				else return v;
			}
			else if ((info.Type == typeof(decimal)) || (info.Type == typeof(decimal?)))
			{
				decimal v;
				if (!decimal.TryParse(value.ToString().Replace("$", string.Empty), out v))
				{
					//If this is an empty string and the field is nullable then return null
					//otherwise thow an error
					if (value.ToString() == string.Empty && IsNullable(info.Field))
						return null;
					else
						throw new Exception("The value for '" + GetDisplayName(info.Field) + "' is not a valid decimal.");
				}
				else return v;
			}

			return null;
		}

		private bool NeedsValidatorRequired(Enum field, bool canHaveRequiredValidation, bool forceRequiredValidation)
		{
			if (canHaveRequiredValidation)
			{
				if (forceRequiredValidation)
					return true;

				return !IsNullable(field);
			}
			return false;
		}

		private bool NeedsValidatorExpression(Enum field)
		{
			return !string.IsNullOrEmpty(GetRegularExpression(field));
		}

		private bool NeedsValidatorMinMax(Enum field)
		{
			if (GetMinValue(field) != null && GetMaxValue(field) != null)
				return true;
			else
				return false;
		}

		private bool IsNullable(Enum field)
		{
			var a = GetMetadata(field).GetType().GetField(field.ToString()).GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.RequiredAttribute), true)
				.FirstOrDefault();
			return (a == null);
		}

		private string DataFormatString(Enum field)
		{
			var a = GetMetadata(field).GetType().GetField(field.ToString()).GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayFormatAttribute), true)
				.FirstOrDefault() as System.ComponentModel.DataAnnotations.DisplayFormatAttribute;
			if (a == null)
				return string.Empty;
			else
				return a.DataFormatString;
		}

		private string GetRegularExpression(Enum field)
		{
			object a =
				GetMetadata(field).GetType().GetField(field.ToString()).GetCustomAttributes(typeof(RegularExpressionAttribute),
																																										true).FirstOrDefault();
			if (a == null) return string.Empty;
			else return ((RegularExpressionAttribute)a).Pattern;
		}

		private string GetDisplayName(Enum field)
		{
			object a =
				GetMetadata(field).GetType().GetField(field.ToString()).GetCustomAttributes(typeof(DisplayAttribute), true).
					FirstOrDefault();
			if (a == null) return field.ToString();
			else return ((DisplayAttribute)a).Name;
		}

		private double? GetMinValue(Enum field)
		{
			object a =
				GetMetadata(field).GetType().GetField(field.ToString()).GetCustomAttributes(typeof(RangeAttribute), true).
					FirstOrDefault();
			if (a == null) return null;
			else
			{
				object v = ((RangeAttribute)a).Minimum;
				if (v is int) return Convert.ToDouble(v);
				else return (double)v;
			}
		}

		private double? GetMaxValue(Enum field)
		{
			object a =
				GetMetadata(field).GetType().GetField(field.ToString()).GetCustomAttributes(typeof(RangeAttribute), true).
					FirstOrDefault();
			if (a == null) return null;
			else
			{
				object v = ((RangeAttribute)a).Maximum;
				if (v is int) return Convert.ToDouble(v);
				else return (double)v;
			}
		}

		/// <summary>
		/// Trys to format a number or date based on a format string
		/// </summary>
		private static string FormatText(object o, string dataFormatString)
		{
			if (o == null) return string.Empty;
			if (string.IsNullOrEmpty(dataFormatString)) return o.ToString();

			if ((o is DateTime) || (o is DateTime?))
			{
				return ((DateTime)o).ToString(dataFormatString);
			}
			else if ((o is decimal) || (o is decimal?))
			{
				return ((decimal)o).ToString(dataFormatString);
			}
			else if ((o is int) || (o is int?))
			{
				return ((int)o).ToString(dataFormatString);
			}
			else if ((o is Single) || (o is Single?))
			{
				return ((Single)o).ToString(dataFormatString);
			}
			else if ((o is double) || (o is double?))
			{
				return ((double)o).ToString(dataFormatString);
			}
			else
			{
				throw new Exception("Cannot format values of type '" + o.GetType().ToString() + "'!");
			}
		}

		#endregion

		#region Private Internal Methods

		private MapConfiguration MapInternal(MapConfiguration configuration)
		{
			if (configuration == null)
				throw new Exception("The configuration object must be set!");
			configuration.Setup(_context);
			if (!configuration.IsValid())
				throw new Exception("The configuration object is not valid!");

			var a = GetMetadata(configuration.Field).GetType().GetField(configuration.Field.ToString()).GetCustomAttributes(typeof(StringLengthAttribute), true).FirstOrDefault();
			if (a != null && configuration.Control is TextBox)
				((TextBox)configuration.Control).MaxLength = ((StringLengthAttribute)a).MaximumLength;

			if (string.IsNullOrEmpty(configuration.DataFormatString))
				configuration.DataFormatString = DataFormatString(configuration.Field);

			_controlList[configuration.Control] = configuration;
			return configuration;
		}

		private MapConfiguration MapPromptInternal(MapConfiguration configuration)
		{
			if (configuration == null)
				throw new Exception("The configuration object must be set!");
			configuration.Setup(_context);
			if (!configuration.IsValid())
				throw new Exception("The configuration object is not valid!");

			_promptControlList[configuration.Control] = configuration;
			return configuration;
		}

		private IMetadata GetMetadata(Enum field)
		{
			return (IMetadata)_context.GetMetaData(_context.GetEntityFromField(field));
		}

		#endregion
	}
}